<?php

declare( strict_types = 1 );

namespace App\Common\Model\Base\DataUnit\WhereDy\JoinWhere;

use App\Common as com;
use App\Common\Model\Base as nameBase;
use App\Common\Model\Base\DataUnit as nameDataUnit;

class Item extends com\Cla\ClaBase {

	protected string $leftJoinTableName;

	protected array $leftJoinFields;

	protected string $defaultLeftJoinTableOfCurrent;

	/**
	 * join表次数
	 * @var array 格式：[ 'join名' => {次数} ]
	 */
	protected array $joinTableCount = [];

	/**
	 * @param nameBase\DataUnit $dataUnit
	 * @throws
	 */
	public function __construct( nameBase\DataUnit $dataUnit ) {
		$this->goWeakReferencePool()->create( 'dataUnit', $dataUnit );
		//
		parent::__construct();
	}

	/**
	 * @return nameBase\DataUnit
	 * @throws
	 */
	protected function getDataUnit(  ):nameBase\DataUnit {
		return $this->goWeakReferencePool()->get( 'dataUnit' );
	}

	/**
	 * 连接当前表
	 * @param \Closure|null $joinFn function( string $relevanceTableNameAs, \Hyperf\Database\Query\JoinClause $joinOnFn )
	 * @param array $params 参数数组
	 * @return string 连接表别名
	 * @throws
	 */
	public function newLeftJoinTableOfCurrent( \Closure $joinFn = null, array $params = [] ):string {
		return $this->newLeftJoinTable( $this->leftJoinTableName, $this->leftJoinFields[0], $this->leftJoinFields[1], $joinFn, $params );
	}

	/**
	 * 连接当前表(只连接一次)
	 * @return string 连接表别名
	 * @throws
	 */
	public function defaultLeftJoinTableOfCurrent():string {
		if( empty( $this->defaultLeftJoinTableOfCurrent ) ){
			$this->defaultLeftJoinTableOfCurrent = $this->newLeftJoinTable( [
				$this->leftJoinTableName,
				$this->applyJoinTableAs( $this->leftJoinTableName, true )
			], $this->leftJoinFields[0], $this->leftJoinFields[1] );
		}
		return $this->defaultLeftJoinTableOfCurrent;
	}

	/**
	 * @param $relevanceTableNameOrAs
	 * @param string $mainFieldName
	 * @param string $relevanceFieldName
	 * @param \Closure|null $joinFn function( string $relevanceTableNameAs, \Hyperf\Database\Query\JoinClause $joinOnFn )
	 * @param array $params
	 * @return string 连接表别名
	 * @throws com\Lib\Err\BaseException\Throw_
	 */
	protected function newLeftJoinTable( $relevanceTableNameOrAs, string $mainFieldName, string $relevanceFieldName, ?\Closure $joinFn = null, array $params = [] ):string {
		// ...
		if( is_string( $relevanceTableNameOrAs ) ){
			$relevanceTableNameAndAs = [
				$relevanceTableNameOrAs,
				$this->applyJoinTableAs( $relevanceTableNameOrAs ),
			];
		} else if( is_array( $relevanceTableNameOrAs ) ){
			$relevanceTableNameAndAs = $relevanceTableNameOrAs;
		} else{
			throw com\Lib\Err\Exception::makeOfNew( '无效的类型', com\Lib\Err\Code::$sysAssertError );
		}
		//
		$this->getDataUnit()->goModelQuery()->leftJoin( "{$relevanceTableNameAndAs[0]} as {$relevanceTableNameAndAs[1]}", function ( \Hyperf\Database\Query\JoinClause $join ) use ( $relevanceTableNameAndAs, $mainFieldName, $relevanceFieldName, $joinFn ) {
			// 检查是否包含了表名
			if( ! str_contains( $mainFieldName, '.' ) ){
				$mainTableName = $this->getDataUnit()->getTableName();
				$mainFieldName = "{$mainTableName}.{$mainFieldName}";
			}
			if( ! str_contains( $relevanceFieldName, '.' ) ){
				$relevanceFieldName = "{$relevanceTableNameAndAs[1]}.{$relevanceFieldName}";
			}
			//
			$join->on( $mainFieldName, '=', $relevanceFieldName );
			//
			if( $joinFn instanceof \Closure ){
				call_user_func_array( $joinFn, [
					$relevanceTableNameAndAs[1],
					$join,
				] );
			}
		} );
		//
		return $relevanceTableNameAndAs[1];
	}

	/**
	 * 申请join别名
	 * @param string $joinTableName
	 * @param bool $isDefault 是否申请默认别名(_0)
	 * @return string
	 */
	protected function applyJoinTableAs( string $joinTableName, bool $isDefault = false ):string {
		if( $isDefault ){
			return $joinTableName . '_0';
		}
		//
		if( ! array_key_exists( $joinTableName, $this->joinTableCount ) ){
			$this->joinTableCount[ $joinTableName ] = 0;
		}
		$this->joinTableCount[ $joinTableName ]++;
		return $joinTableName . '_' . $this->joinTableCount[ $joinTableName ];
	}

}
